package com.ctrip.cap.device;

import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author ltyao
 *
 * @param <T>
 */
public abstract class AbstractDeviceStore<T extends Device> implements
		DeviceStore<T> {

	protected static final Logger log = LoggerFactory
			.getLogger(AbstractDeviceStore.class);

	protected final ReentrantLock lock;
	protected final Condition notEmpty;
	protected final TreeSet<Device> devicesInUse = new TreeSet<>();
	protected final Set<T> devices = new TreeSet<>();

	protected AbstractDeviceStore() {
		lock = new ReentrantLock(true);
		notEmpty = lock.newCondition();
	}

	@Override
	public Device take() throws InterruptedException {
		final ReentrantLock lock = this.lock;
		lock.lockInterruptibly();
		try {
			// log.debug("devices in use size {}", devicesInUse);
			while (devicesInUse.isEmpty()) {
				log.debug("take need wait ....");
				notEmpty.await();
			}
			return devicesInUse.pollFirst();

		} finally {
			lock.unlock();
		}
	}

	@Override
	public void put(Device device) {
		final ReentrantLock lock = this.lock;
		lock.lock();
		try {
			devicesInUse.add(device);
			notEmpty.signal();
		} finally {
			lock.unlock();
		}

	}

	@Override
	public Set<T> getDevices() {
		return new TreeSet<T>(devices);
	}

}